package samples;

import choco.integer.IntVar;
import choco.palm.Explanation;
import choco.palm.PalmProblem;
import choco.palm.dbt.integer.PalmIntDomain;
import choco.palm.dbt.integer.PalmIntVar;

public class MagicSquare {

    public static void main(String[] args) {
        int n = 4;
        System.out.println("Magic Square Problem with n = " + n);
        PalmProblem myPb = new PalmProblem();
        IntVar[] vars = new IntVar[n * n];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++) {
                vars[i * n + j] = myPb.makeEnumIntVar("C" + i + "_" + j, 1, n *
                        n);
            }
        IntVar sum = myPb.makeEnumIntVar("S", 1, n * n * (n * n + 1) / 2);
        myPb.post(myPb.eq(sum, n * (n * n + 1) / 2));
        for (int i = 0; i < n * n; i++)
            for (int j = 0; j < i; j++)
                myPb.post(myPb.neq(vars[i], vars[j]));
        int[] coeffs = new int[n];
        for (int i = 0; i < n; i++) {
            coeffs[i] = 1;
        }
        for (int i = 0; i < n; i++) {
            IntVar[] col = new IntVar[n];
            IntVar[] row = new IntVar[n];

            for (int j = 0; j < n; j++) {
                col[j] = vars[i * n + j];
                row[j] = vars[j * n + i];
            }
            myPb.post(myPb.eq(myPb.scalar(coeffs, row), sum));
            myPb.post(myPb.eq(myPb.scalar(coeffs, col), sum));
        }
        myPb.solve();
        Explanation expl = ((PalmProblem) myPb).makeExplanation();
        ((PalmIntVar) vars[3]).self_explain(PalmIntDomain.VAL, 2, expl);
        System.out.println("Why " + vars[3] + " =! 2 : " + expl);
    }
}
